State and Lifecycle
code:JavaScript
function Clock(props) {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {props.date.toLocaleTimeString()}.</h2>
</div>
);
}
function tick() {
ReactDOM.render(
<Clock date={new Date()} />,
document.getElementById('root')
);
}
setInterval(tick, 1000);
これだとClockコンポーネントがタイマーをセットアップしたりUIを更新したりしてない。
なので以下のように実装したい。
code:JavaScript
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
ここで登場するのがstate。
stateはpropsと同じだけど、privateかつコンポーネントによってコントロールされる必要がある
ES6のクラスであればローカルstateを実現できる
Converting a Function to a Class
クラスのrenderメソッドは更新が発生するたびに呼ばれる
しかし<Clock />のインスタンスは1つが使い回される
クラスにしたことで、ローカルstateやライフサイクルメソッドが使える
Adding Local State to a Class
constructorを置いて、super(props)したあとにthis.stateでローカルstateを定義する
Adding Lifecycle Methods to a Class
コンポーネント破棄の際にリソースを解放するのが大事
初めてDOMにレンダリングされたこと="mounting"
componentDidMount()
コンポーネントが削除されたDOMが生成されたこと="unmounting"
componentWillUnmount()
Using State Correctly
setStateで知るべき3つのこと
Do Not Modify State Directly
this.stateはコンストラクタでのみ値の割り当てが可能
code:JavaScript
// Wrong
this.state.comment = 'Hello';
// Correct
this.setState({comment: 'Hello'});
State Updates May Be Asynchronous
setStateはパフォーマンスの観点から1度だけコールする
this.propsやthis.stateの更新は非同期で行われるので次のstateの計算はそれらに依存すべきではない
code:JavaScript
// Wrong
this.setState({
counter: this.state.counter + this.props.increment,
});
// Correct
this.setState((state, props) => ({
counter: state.counter + props.increment
}));
// Correct
this.setState(function(state, props) {
return {
counter: state.counter + props.increment
};
});
※このときにstateとpropsに与えられる内容に注意する
table:arguments
state the previous state
props at the time the update is applied
State Updates are Merged
setStateを呼ぶと、引数で与えたデータとマージする
The Data Flows Down
コンポーネントツリーの下にしか影響を与えない単方向・トップダウンデータフロー
stateful/statelessのどちらも、どちらかを含むコンポーネントにすることができる